http://bit.ly/jmb_cpoa http://iut-blagnac.github.io/cpoa/
Ce cours porte sur la Conception et Programmation Objet Avancée.
Vous avez appris (cf. M2103 et M2104) un certain nombre de concepts objets :
Vous avez/allez ensuite appris des bonnes pratiques :
L’étape suivante consiste à apprendre les bonnes solutions de conception, ce qu’on appelle les patrons de conception (ou design patterns en anglais).
|
|
Rappel du rythme : 1 cours, 1 TD et 2 TPs par semaine. Pendant 8 semaines. |
Les 5 suivantes sont consacrées à l’étude de certains patrons classiques. Mise en pratique sur des exercices en TP.
|
|
Les TPs sont décalés d’une semaine (conception et étude d’un ou
plusieurs patrons semaine |
Voici une proposition de déroulement des semaines :
SuperCanard, le grand classique, [Stratégie]
L’exemple de Meyer : menus en objet
Premiers patrons
Observable)Patrons Fabrique, Proxy, Etat
Patrons Décorateur, Façade, Visiteur
JTable de JavaQuelques idées de projet final :
Comme prévu par le planning des contrôles, les étudiants auront :
Le fait d’attribuer un type (une classe) à une variable (un objet) peut se faire de plusieurs façons :
On parle de typage statique quand la majorité des vérifications de type sont effectuées au moment de la compilation.
int i = 0; // cette déclaration indique explicitement que
// la variable i est de type entier
Le typage dynamique consiste à laisser l’ordinateur réaliser l’opération de typage à la volée, lors de l’exécution du code.
/**
* @author André Peninou
*/
public class Type {
void m() {
System.out.println ("Type");
}
}
public class SousType extends Type {
void m() {
System.out.println ("SousType");
}
void autreM(){
System.out.println ("Spécifique SousType");
}
}
...
Type a = new Type();
a.m(); // "Type"
a = new SousType();
a.m(); // "SousType"
// Statique : a est un Type (à la compil)
// Dynamique : a est un SousType au runtime.
// D'où :
a = new SousType();
a.autreM();
// NOK car type statique == A => autreM() n'existe pas à la compilation
...
Style de typage dynamique où la sémantique d’un objet (c’est-à-dire son type) est déterminée par l’ensemble de ses méthodes et de ses attributs, et non par un type défini et nommé explicitement par le programmeur.
|
|
L’origine de cette expression est liée à cette citation :
|
def calcule(a, b, c)
return a*b+c
end
$a = calcule(6, 3, 2)
$b = calcule('6', 3, ', the number of the beast')
puts $a.to_s
puts $b.to_s
Ce qui donne :
20 666, the number of the beast
|
|
Pour aller plus loin : http://fr.wikipedia.org/wiki/Duck_typing |
Dès que l’on commence à avoir une application conséquente, l’organisation en package devient obligatoire. Revenons donc sur les questions de visibilité des propriétés et méthodes, qui seront importants dans la plupart des aspects de ce module.
Si un champ d’une classe A :
A mais de nulle part ailleurs ;A et,
si A est publique, grosso modo dans les classes héritant de A dans d’autres
paquetages ;A et,
si A est publique, de partout ailleurs.|
|
Ci-dessus, les niveaux de visibilité sont rangés par visibilité croissante. |
package UN;
public class A {
protected String attrprotected;
String attrfriend; // friend
}
Si on définit une deuxième classe dans le même package :
package UN;
class B {
...
{
A a = new A ();
a.attrprotected// OK : même si bizarre
a.attrfriend // OK : visible package
}
}
package UN;
class C extends A {
...
{
this.attrprotected// OK : normal
this.attrfriend // OK : visible package
}
}
package DEUX;
class B {
...
{
A a = new A ();
a.attrprotected// NON OK : normal
a.attrfriend // NON OK : normal, proche de "private"
}
}
class C extends A {
...
{
this.attrprotected// OK : normal car protected et héritage
this.attrfriend // NON OK : normal, proche de "private"
}
}
À la question private ou protected ? Quel est le mieux pour les attributs ?
private|
|
Il n’y a pas de visibilité par défaut en UML™. |
–––––––––––––––––– Science is what we understand well enough to explain to a computer. Art is everything else we do. ––––––––––––––––––Donald Knuth
|
|
Principe de conception
|
|
|
Principe de conception
|
|
|
Principe de conception
|
|
|
Design pattern : Stratégie (Strategy)
Stratégie définit une famille d’algorithmes, encapsule chacun d’eux et les rend interchangeables. Il permet à l’algorithme de varier indépendamment des clients qui l’utilisent. |
|
|
Pourquoi n’a-t’on pas utilisé Strategy pour afficher() ou nager()?
|
|
|
Cet exemple est tiré de ce cours. |
Le problème
Vous avez une classe FileWriter qui a pour rôle d’écrire dans un fichier
ainsi qu’une classe DBWriter. Dans un premier temps, ces classes ne
contiennent qu’une méthode write() qui n’écrira que le texte passé
en paramètre.
Au fil du temps, vous vous rendez compte que c’est dommage qu’elles ne fassent que ça et vous aimeriez bien qu’elles puissent écrire en différents formats (HTML, XML, etc.) : les classes doivent donc formater puis écrire.
La solution
|
|
L’interface en
PHP (code source ici)
|
|
|
La classe abstraite
Writer (code source ici)
|
|
|
La classe
FileWriter (code source ici)
|
|
|
La classe
DBWriter (code source ici)
|
Enfin, nous avons nos trois formateurs.
L’un ne fait rien de particulier (TextFormater),
et les deux autres formatent le texte en deux langages
différents (HTMLFormater et XMLFormater).
|
|
La classe
TextFormater (code source ici)
|
|
|
La classe
HTMLFormater (code source ici)
|
|
|
La classe
XMLFormater (code source ici)
|
La fonction standard sort() de python
>>> sorted("This is a test string from Andrew".split(), key=str.lower)
['a', 'Andrew', 'from', 'is', 'string', 'test', 'This']
Stratégie de cryptage en fonction de la taille d’un fichier
File file = getFile();
Cipher c = CipherFactory.getCipher( file.size() );
c.performAction();
// implementations:
interface Cipher {
public void performAction();
}
class InMemoryCipherStrategy implements Cipher {
public void performAction() {
// load in byte[] ....
}
}
class SwaptToDiskCipher implements Cipher {
public void performAction() {
// swapt partial results to file.
}
}
|
|
Plus de détails ici |
|
|
Les patrons ne sont pas réutilisables! |
Il faut implémeter la solution qu’il représente à chaque fois.
Exception : certains font l’objet d’une librairie.
Par exemple le patron Singleton existe dans la bibliothèque standard du langage en Ruby. C’est un mixin qu’il suffit d’inclure dans la classe qui doit être un singleton.
class Klass
include Singleton
# ...
end
a,b = Klass.instance, Klass.instance
a == b
# => true
Klass.new
# => NoMethodError - new is private ...
Alexander : patterns pour les architectures (les vraies)
Beck et Cunningham : patterns pour des interfaces utilisateurs
Meyer : livre sur l’orienté objet (langage Eiffel), devenu la bible pour beaucoup de programmeurs (cf. [Meyer88])
Gamma, Helm, Johnson et Vlissides : LE livre de référence (cf. [GoF]) NOTE: Les patterns de ce livre sont connus comme les Gof pour « Gang of Four ».
Martin : principes SOLID (cf. [Martin03])
Craig Larman décrit des modèles de conception : les Patterns GRASP (cf. [Larman05])
SOLID:
Responsabilité => Sujet à changement
Ouvert à l'extension mais fermé à la modification
|
|
Une fois écrite et testée, une classe ne devrait être modifiée que pour être corrigée! Toute modification devrait être possible par extension. |
Une classe doit pouvoir être remplacée par une instance d'un de ses sous-types, sans modifier la cohérence du programme
Un carré est un rectangle a deux côtés égaux.
|
|
Peut-on toujours substituer un Carré à la place d’un Rectangle ?
|
Préférer plusieurs interfaces spécifiques pour chaque client plutôt qu'une seule interface générale
Il faut dépendre des abstractions, pas des implémentations
Ce principe indique :
|
|
Ainsi ce principe va à l’encontre de l’intuition classique. |
|
|
QUESTION
Lesquels des 5 principes SOLID s’appliquent bien à Strategy ? |
Quelques éléments de réponses :
Bof
⇒ Oui : extension (du comportement) sans toucher au code!
Non
Oui, mais pas spécifiquement
⇒ Oui : les algos dépendent des mêmes abstractions que les données (les interfaces)
The critical design tool for software development is a mind well educated in design principles. It is not the UML or any other technology.
Craig Larman, 2005
Il s’agit d’un ensemble de patrons, plutôt orientés conception (UML). Nous en aborderons certains au travers des exemples de ce module (cf. [Larman05]).
T’as qu’à utiliser une factory!
|
|
QUESTION
Qui fait la nuit de l’info dans un groupe avec des Masters? |
Exemple de Strategy :
Strategy
Situations où il est nécessaire de permuter dynamiquement les algorithmes utilisés
Définir une famille d’algorithmes, encapsuler chacun d’eux en tant qu’objet, et les rendre interchangeables.
Ce patron laisse les algorithmes changer indépendamment des clients qui les emploient.
Ceux déjà pratiqués
Les "pressentis"
Les nouveaux
Les "avancés"
Ceux qu’on n’aura pas le temps d’aborder
Concepts avancés
|
|
QUESTION
|
|
|
Ces définitions seront enrichies au fur et à mesure des patrons étudiés. |
Fabrique (simple) définit une interface pour la création d’un objet, mais en laissant à des sous-classes le choix des classes à instancier (voir aussi Fabrique abstraite).
Fabrique (abstraite) fournit une interface pour la création de familles d’objets apparentés ou interdépendants, sans qu’il soit nécessaire de spécifier leurs classes concrètes (voir aussi Fabrique).
Observateur définit une relation entre objets de type un-à-plusieurs, de façon que, lorsqu’un objet change d’état, tous ceux qui en dépendent en soient notifiés et soient mis à jour automatiquement.
Stratégie définit une famille d’algorithmes, encapsule chacun d’eux et les rend interchangeables. Il permet à l’algorithme de varier indépendamment des clients qui l’utilisent.
cysboy. Disponible ici (le 2014-11-19).Les diagrammes UML™ sont réalisés avec plantUML avec des conventions graphiques propres qui sont listées ci-dessous.
Document réalisé par Jean-Michel Bruel via Asciidoctor (version 1.5.1) de 'Dan Allen', lui même basé sur AsciiDoc.
Pour l’instant ce document est libre d’utilisation et géré par la 'Licence Creative Commons'.
licence Creative Commons Paternité - Partage à l'Identique 3.0 non transposé.
/